package com.coderising.array;

import org.junit.experimental.max.MaxCore;

public class ArrayUtil {

	/**
	 * 给定一个整形数组a , 对该数组的值进行置换 例如： a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] 如果 a =
	 * [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7]
	 * 
	 * @param origin
	 * @return
	 */
	public static void reverseArray(int[] origin) {
		if (origin.length < 2)
			return;
		int temp;
		for (int i = 0; i < origin.length >> 1; i++) {
			temp = origin[i];
			origin[i] = origin[origin.length - 1 - i];
			origin[origin.length - 1 - i] = temp;
		}
	}

	/**
	 * 现在有如下的一个数组： int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}
	 * 要求将以上数组中值为0的项去掉，将不为0的值存入一个新的数组，生成的新数组为： {1,3,4,5,6,6,5,4,7,6,7,5}
	 * 
	 * @param oldArray
	 * @return
	 */

	public static int[] removeZero(int[] oldArray) {
		if (oldArray == null || oldArray.length == 0)
			return null;
		int zeros = 0;// 数组中0元素的个数
		for (int i = 0; i < oldArray.length; i++) {
			if (oldArray[i] == 0)
				zeros++;
		}
		int[] newArr = new int[oldArray.length - zeros];
		for (int i = 0, j = 0; i < oldArray.length; i++) {
			if (oldArray[i] != 0) {
				newArr[j] = oldArray[i];
				j++;
			}
		}
		return newArr;
	}

	/**
	 * 给定两个已经排序好的整形数组， a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素， 并且仍然是有序的 例如 a1 =
	 * [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意： 已经消除了重复
	 * 
	 * @param array1
	 * @param array2
	 * @return
	 */

	public static int[] merge(int[] array1, int[] array2) {
		int[] mergedArr = new int[array1.length + array2.length];
		int temp;
		int i = 0, j = 0, index = 0, size = 0;
		while (i < array1.length && j < array2.length) {
			//两个数组都没遍历到最后一个元素
			if (i != array1.length - 1 && j != array2.length - 1) {
				if (array1[i] < array2[j]) {
					temp = array1[i++];
				} else if (array1[i] > array2[j]) {
					temp = array2[j++];
				} else {
					//遇到相等元素，存放任意一个就实现去重了
					temp = array1[i++];
					j++;
				}
				mergedArr[index++] = temp;
				size++;
			//array1遍历到最后一个元素
			} else if (i == array1.length - 1 && j != array2.length - 1) {
				if (array1[i] < array2[j]) {
					temp = array1[i];
					mergedArr[index++] = temp;
					size++;
					//将array2的剩余元素复制到mergedArr中
					System.arraycopy(array2, j, mergedArr, index, array2.length - j);
					size += array2.length - j;
					break;
				} else if (array1[i] > array2[j]) {
					temp = array2[j++];
					size++;
				} else {
					System.arraycopy(array2, j, mergedArr, index, array2.length - j);
					size += array2.length - j;
					break;
				}
			//array2遍历到最后一个元素
			} else if (i != array1.length - 1 && j == array2.length - 1) {
				if (array1[i] > array2[j]) {
					temp = array2[j];
					mergedArr[index++] = temp;
					size++;
					//将array1的剩余元素复制到mergedArr中
					System.arraycopy(array1, i, mergedArr, index, array1.length - i);
					size += array1.length - i;
					break;
				} else if (array1[i] < array2[j]) {
					temp = array2[i++];
					size++;
				} else {
					System.arraycopy(array1, i, mergedArr, index, array1.length - i);
					size += array1.length - i;
					break;
				}
			}
		}
		//构造新数组，去除mergedArr中尾部若干0元素
		int[] result = new int[size];
		System.arraycopy(mergedArr, 0, result, 0, size);
		return result;
	}

	/**
	 * 把一个已经存满数据的数组 oldArray的容量进行扩展， 扩展后的新数据大小为oldArray.length + size
	 * 注意，老数组的元素在新数组中需要保持 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为
	 * [2,3,6,0,0,0]
	 * 
	 * @param oldArray
	 * @param size
	 * @return
	 */
	public static int[] grow(int[] oldArray, int size) {
		int[] arr = new int[oldArray.length + size];
		System.arraycopy(oldArray, 0, arr, 0, oldArray.length);
		return arr;
	}

	/**
	 * 斐波那契数列为：1，1，2，3，5，8，13，21...... ，给定一个最大值， 返回小于该值的数列 例如， max = 15 ,
	 * 则返回的数组应该为 [1，1，2，3，5，8，13] max = 1, 则返回空数组 []
	 * 
	 * @param max
	 * @return
	 */
	public static int[] fibonacci(int max) {
		if (max < 2) return null;
		int[] a = new int[max];
		a[0] = 1;
		a[1] = 1;
		int size = 2;
		for (int i = 2;; i++) {
			a[i] = a[i-1] + a[i-2];
			if (a[i] > max) break;
			size ++;
		}
		int[] fibonacci = new int[size];
		System.arraycopy(a, 0, fibonacci, 0, size);
		return fibonacci;
	}

	/**
	 * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19]
	 * 
	 * @param max
	 * @return
	 */
	public static int[] getPrimes(int max) {
		if (max < 2) {
			return null;
		}
		int[] a = new int[max];
		int size = 0;
		for (int i = 2; i < max; i++) {
			if (isPrime(i)) {
				a[size++] = i;
			}
		}
		int[] primes = new int[size];
		System.arraycopy(a, 0, primes, 0, size);
		return primes;
	}
	private static boolean isPrime(int i) {
		for (int j = 2; j*j <= i; j++) {
			if (i % j == 0) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 所谓“完数”， 是指这个数恰好等于它的因子之和，例如6=1+2+3 给定一个最大值max， 返回一个数组， 数组中是小于max 的所有完数
	 * 
	 * @param max
	 * @return
	 */
	public static int[] getPerfectNumbers(int max) {
		int[] a = new int[max];
		int size = 0;
		for (int i = 6; i < max; i++) {
			if (isPerfectNumber(i)) {
				a[size++] = i;
			}
		}
		int[] perfectNumbers = new int[size];
		System.arraycopy(a, 0, perfectNumbers, 0, size);
		return perfectNumbers;
	}
	private static boolean isPerfectNumber(int i) {
		int sum = 0;
		for (int j = 1; j <= i >> 1; j++) {
			if (i % j == 0) {
				sum += j;
			}
		}
		if (i == sum) return true;
		else return false;
	}

	/**
	 * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9"
	 * 
	 * @param array
	 * @param s
	 * @return
	 */
	public static String join(int[] array, String seperator) {
		StringBuilder sb = new StringBuilder();
		for (int i : array) {
			sb.append(i);
			sb.append(seperator);
		}
		return sb.substring(0, sb.lastIndexOf(seperator));
	}

}
